跳到主要内容

Java IO学习-打印流

IO流工具类一览

10.png

PrintStream

1、PrintStream 和 PrintWriter 类都提供了一系列重载的 print 和 println 方法来输出各种类型的数据。 2、PrintStream 和 PrintWriter 的输出操作不会抛出异常。 3、System.out 就是 PrintStream 的一个实例。

平时在控制台打印输出都是调用 print 方法和 println 方法完成的,实际这两个方法都是 PrintStream 类,输出到控制台都是使用这个类

PrintStream 流有自动刷新机制,例如当向 PrintStream 流中写入一个字节数组后自动调用 flush() 方法。

PrintStream 将基本的数据类型的数据或引用数据类型的对象格式化成字符串后再输出。使用该类不必书写转化成字符串的操作方法 toString(),可以直接输出。

PrintStream 可以通过 System.setOut() 改变 System.out 不用打印到控制台,而且转到其他媒介。

PrintStream 一般用得比较少,它能做的 PrintWriter 也都能实现,并且 PrintWriter 的功能更为强大,所以可以替代。

//使用指定的文件创建一个新的打印流,而不需要自动换行。  
PrintStream(File file)
//使用指定的文件和字符集创建新的打印流,而不需要自动换行。
PrintStream(File file, String csn)
//创建一个新的打印流。
PrintStream(OutputStream out)
//创建一个新的打印流。
PrintStream(OutputStream out, boolean autoFlush)
//创建一个新的打印流。
PrintStream(OutputStream out, boolean autoFlush, String encoding)
//使用指定的文件名创建新的打印流,无需自动换行。
PrintStream(String fileName)

常用方法

//将指定的字节写入管道输出流。
public void write(int b)
public void write(byte[] b,int off,int len)

// 和控制台那个是一样的
public void println()

//追加数据到输出流
public PrintStream append(char c)
public PrintStream append(CharSequence csq,int start,int end)
public PrintStream append(CharSequence csq)
//关闭输出流
public void close()
//刷新输出流
public void flush()

printf 的格式控制的完整格式:

%c        单个字符 
%d 十进制整数
%f 十进制浮点数
%o 八进制数
%s 字符串
%u 无符号十进制数
%x 十六进制数
%% 输出百分号%

例如:%5d 输出的整型值占5位宽度,不足5位的话,在左边用空格补充

public class learn01 {

public static void main(String[] args) throws IOException {
String name = "a.txt";
String path = "C:\\Users\\alsritter\\Desktop";
File file = new File(path, name);

//用来测试程序的效率,所以读取前后时间
long s = System.currentTimeMillis();

FileOutputStream fos = new FileOutputStream(file);
PrintStream printStream = new PrintStream(fos);
//平时怎么折腾控制台这里就怎么折腾



printStream.println("helloWorld");
printStream.println(12345);
printStream.println(new Date());

// 将输出定向到文件
System.setOut(printStream);
System.out.println("put to file");

// 毕竟是流,还是需要释放资源的
printStream.close();


// 返回当前毫秒
long e = System.currentTimeMillis();
System.out.println("共耗时:"+(e - s)+"毫秒");
}
}

改变打印流向

参考资料 简书-System的PrintStream对象out何时实例化的

System.out 就是 PrintStream 类型的,只不过它默认流向的是控制台,所以如有需要可以手动改变其流向 (例如流向日志文件)

在替换 System.out 默认的 PrintStream 之前需要先保存,以便于之后还原

public class learn01 {

public static void main(String[] args) throws IOException {

String name = "a.txt";
String path = "C:\\Users\\alsritter\\Desktop";
File file = new File(path, name);

//用来测试程序的效率,所以读取前后时间
long s = System.currentTimeMillis();

PrintStream printStream = new PrintStream(file);
//注意!!!修改前需要保存系统控制台
PrintStream standard = System.out;
// 改变System.out的输出目的地
System.setOut(printStream);
System.out.println("helloWorld");
System.out.println(12345);
System.out.println(new Date());

// 释放资源后,再改回系统控制台
printStream.close();
System.setOut(standard);

// 返回当前毫秒
long e = System.currentTimeMillis();
System.out.println("共耗时:"+(e - s)+"毫秒");
}
}

PrintWrite

PrintWriter 是字符类型的打印输出流,它继承于 Writer。它用于向文本输出流打印对象的格式化表示形式。它实现在 PrintStream 中的所有 print 方法。它不包含用于写入原始字节的方法,对于这些字节,程序应该使用未编码的字节流进行写入。

内部关键字

protected Writer out;                   // 传入的底层字符输出流  
private boolean autoFlush = false; // 是否自动刷新
private boolean trouble = false; // 是否抛异常
private Formatter formatter; // 格式化类
private PrintStream psOut = null; // 字节打印流、用于checkError方法

构造函数

// 使用指定文件创建不具有自动行刷新的新 PrintWriter。
PrintWriter(File file)

// 创建具有指定文件和字符集且不带自动刷行新的新 PrintWriter。
PrintWriter(File file, String csn)

// 根据现有的 OutputStream 创建不带自动行刷新的新 PrintWriter。
PrintWriter(OutputStream out)

// 通过现有的 OutputStream 创建新的 PrintWriter。
PrintWriter(OutputStream out, boolean autoFlush)

// 创建具有指定文件名称且不带自动行刷新的新 PrintWriter。
PrintWriter(String fileName)

// 创建具有指定文件名称和字符集且不带自动行刷新的新 PrintWriter。
PrintWriter(String fileName, String csn)

// 创建不带自动行刷新的新 PrintWriter。
PrintWriter(Writer out)

// 创建新 PrintWriter。
PrintWriter(Writer out, boolean autoFlush)

常用方法

PrintWriter append(char c)    // 将指定字符添加到此 writer。   
PrintWriter append(CharSequence csq) // 将指定的字符序列添加到此 writer。
PrintWriter append(CharSequence csq, int start, int end) // 将指定字符序列的子序列添加到此 writer。
boolean checkError() // 如果流没有关闭,则刷新流且检查其错误状态。

protected void clearError() // 清除此流的错误状态。
void close() // 关闭该流并释放与之关联的所有系统资源。
void flush() // 刷新该流的缓冲。

PrintWriter format(Locale l, String format, Object... args) // 使用指定格式字符串和参数将一个格式化字符串写入此 writer 中。
PrintWriter format(String format, Object... args) // 使用指定格式字符串和参数将一个格式化字符串写入此 writer 中。

void print(boolean b) // 打印 boolean 值。
void print(char c) // 打印字符。
void print(char[] s) // 打印字符数组。
void print(double d) // 打印 double 精度浮点数。
void print(float f) // 打印一个浮点数。
void print(int i) // 打印整数。
void print(long l) // 打印 long 整数。
void print(Object obj) // 打印对象。
void print(String s) // 打印字符串。

PrintWriter printf(Locale l, String format, Object... args) // 使用指定格式字符串和参数将格式化的字符串写入此 writer 的便捷方法。
PrintWriter printf(String format, Object... args) // 使用指定格式字符串和参数将格式化的字符串写入此 writer 的便捷方法。

void println() // 通过写入行分隔符字符串终止当前行。
void println(boolean x) // 打印 boolean 值,然后终止该行。
void println(char x) // 打印字符,然后终止该行。
void println(char[] x) // 打印字符数组,然后终止该行。
void println(double x) // 打印双精度浮点数,然后终止该行。
void println(float x) // 打印浮点数,然后终止该行。
void println(int x) // 打印整数,然后终止该行。
void println(long x) // 打印 long 整数,然后终止该行。
void println(Object x) // 打印 Object,然后终止该行。
void println(String x) // 打印 String,然后终止该行。

protected void setError() // 指示已发生错误。

void write(char[] buf) // 写入字符数组。
void write(char[] buf, int off, int len) // 写入字符数组的某一部分。
void write(int c) // 写入单个字符。
void write(String s) // 写入字符串。
void write(String s, int off, int len) // 写入字符串的某一部分。

使用例

public static void main(String[] args) throws IOException {        
//创建一个字符打印流对象
PrintWriter pw = new PrintWriter(new FileWriter("pw.txt")) ;
//写数据
pw.println("hello");//本身自动换行并且向pw.txt文件打印内容

pw.flush(); //本身在构造的时候,就可以启动自动刷新 (把缓存的数据刷新到文件中)

//关闭流
pw.close();
}

write 与 print的区别

  1. print方法可以将各种类型的数据转换成字符串的形式输出。
  2. 重载的 write 方法只能输出字符、字符数组、字符串等与字符相关的数据。

InputStreamReader 控制台输入

//准备数据:控制台读取 System.in
BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));

Scanner 控制台输入

使用上面那个 Scanner 实际区别不大,主要多提供了一些 API

// 获取系统输入
Scanner input=new Scanner(System.in);
String str=new input.next();
int n=input.nextInt();

next() 用于读取下一个输入(一个空格表示下一段)

//输入1 2 3 输出为6
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
Integer a = input.nextInt();
Integer b = input.nextInt();
Integer c = input.nextInt();
System.out.println(a + b + c);
}

java里常使用的方法 next()nextLine() 区别

next():

  1. 一定要读取到有效字符后才可以结束输入。
  2. 对输入有效字符之前遇到的空白,next() 方法会自动将其去掉。
  3. 只有输入有效字符后才将其后面输入的空白作为分隔符或者结束符。
  4. next() 不能得到带有空格的字符串。

nextLine():

  1. 以 Enter 为结束符,也就是说 nextLine() 方法返回的是输入回车之前的所有字符
  2. 可以获得空白。

BufferedReader、Scanner 区别

参考资料 Scanner vs. BufferedReader

BufferedReader 是同步的,但 Scanner 不是同步的,这意味着无法在多个线程之间共享 Scanner。 BufferedReader 是线程安全的,但 Scanner 不是线程安全的。 BufferedReader 具有较大的缓冲存储器,而 Scanner 具有较小的缓冲存储器。 BufferedReader 速度更快,但 Scanner 执行速度较慢。

PrintWriter 与 Scanner 的使用

参考资料 Socket之 PrintWriter 与 Scanner的使用

注意:使用 Scanner 的 readLine 获取消息时,这边的 PrintWriter 就必须用 print 而不能用 write,否则会导致消息获取不了

基本使用

public class TestPS {

public static void main(String[] args) throws Exception {

Socket socket = new Socket();

Scanner scan1 = new Scanner(System.in);//用作键盘录入
Scanner scan2 = new Scanner(new File("aa.txt"));//用作文件读取
Scanner scan3 = new Scanner(socket.getInputStream());//网络通信里面去读取对方发给我的信息

scan1.nextLine();//读取键盘录入的信息
scan2.nextLine();//读取文件里面的信息
scan3.nextLine();//读取socket流里面的信息(服务端或者客户端发送的)


PrintWriter pw1 = new PrintWriter(System.out);
PrintWriter pw2 = new PrintWriter("aa.txt");
PrintWriter pw3 = new PrintWriter(socket.getOutputStream());

//使用输出之后一定要flush
pw1.println("控制台打印");pw1.flush();
pw2.println("写到文件里面");pw2.flush();
pw3.println("发送给服务器或者客户端");pw3.flush();

}
}

在 socket 中应用

服务端

public class DemoService {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(8888);
System.out.println("服务器启动...");

Socket service = serverSocket.accept();

//读取客户端发来的消息
Scanner scan = new Scanner(service.getInputStream());
String msg = scan.nextLine();
System.out.println("客户端说:" + msg);

//发送消息给客户端
PrintWriter pw = new PrintWriter(service.getOutputStream());
pw.println("你好!"); //输出信息到缓冲
pw.flush(); //必须,从缓冲丢给你,并且把缓冲刷新

} catch (IOException e) {
e.printStackTrace();
}
}
}

客户端

public class DemoClient {
static int port = 8888;
static String ip = "127.0.0.1";

public static void main(String[] args) {

try {
Socket client = new Socket(ip,port);

//发送消息给服务端
PrintWriter pw = new PrintWriter(client.getOutputStream());
pw.println("你好!");
pw.flush();

//读取服务端发来的消息
Scanner scan = new Scanner(client.getInputStream());
String msg = scan.nextLine();
System.out.println("服务端说:" + msg);


} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}